<template>
  <ToolbarButton
    icon="i-ri-image-line"
    title="图片"
    :active="false"
    :large-icon="props.largeIcon"
    :hide-text="props.hideText"
    @click="handleClick"
  />

  <!-- 图片对话框 -->
  <Dialog
    v-model="showDialog"
    title="插入图片"
    width="480px"
    @close="handleCancel"
  >
    <el-tabs v-model="activeTab" class="image-insert-tabs">
      <el-tab-pane label="网络图片" name="url">
        <el-form :model="{ imageUrl }" label-width="80px" size="small">
          <el-form-item label="图片地址:">
            <el-input
              v-model="imageUrl"
              placeholder="https://example.com/image.jpg"
              @keyup.enter="handleInsertFromUrl"
            />
          </el-form-item>
          <el-form-item>
            <el-button
              type="primary"
              :loading="loading"
              :disabled="!isValidUrl"
              @click="handleInsertFromUrl"
            >
              插入图片
            </el-button>
          </el-form-item>
        </el-form>
      </el-tab-pane>
      <el-tab-pane label="本地图片" name="upload">
        <div class="image-upload-area">
          <el-upload
            v-if="!previewImage"
            ref="uploadRef"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="handleFileChange"
            accept="image/*"
            drag
          >
            <div class="upload-content">
              <i class="i-ri-upload-cloud-2-line upload-icon"></i>
              <div class="upload-text">点击或拖拽文件到此区域上传</div>
              <div class="upload-hint">支持 JPG、PNG、GIF 等格式</div>
            </div>
          </el-upload>
          <div v-if="previewImage" class="image-preview">
            <div class="image-preview-container">
              <img :src="previewImage" alt="预览" />
            </div>
            <div class="image-preview-actions">
              <el-button size="small" @click="handleRemovePreview">移除</el-button>
              <el-button type="primary" size="small" :loading="loading" @click="handleInsertFromFile">
                插入图片
              </el-button>
            </div>
          </div>
        </div>
      </el-tab-pane>
    </el-tabs>
  </Dialog>
</template>

<script setup lang="ts">
import { ref, computed, inject, nextTick, type Ref } from "vue";
import type { Editor } from "@tiptap/vue-3";
import type { EditorProps } from "../../../../types";
import ToolbarButton from "../../../button/index.vue";
import { Dialog } from "../../../dialog";
import type { UploadFile } from "element-plus";

/**
 * 将图片URL转换为base64
 */
async function imageUrlToBase64(url: string): Promise<string> {
  try {
    const response = await fetch(url);
    const blob = await response.blob();
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = () => {
        if (typeof reader.result === "string") {
          resolve(reader.result);
        } else {
          reject(new Error("Failed to convert image to base64"));
        }
      };
      reader.onerror = reject;
      reader.readAsDataURL(blob);
    });
  } catch (error) {
    console.error("Failed to convert image URL to base64:", error);
    throw error;
  }
}

/**
 * 将文件转换为base64
 */
function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => {
      if (typeof reader.result === "string") {
        resolve(reader.result);
      } else {
        reject(new Error("Failed to convert file to base64"));
      }
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * 检查URL是否为base64
 */
function isBase64Image(src: string): boolean {
  return src.startsWith("data:image/");
}

defineOptions({
  name: "Image",
});

const props = withDefaults(
  defineProps<{
    largeIcon?: boolean;
    hideText?: boolean;
  }>(),
  {
    largeIcon: false,
    hideText: true,
  }
);

// 注入编辑器实例和配置
const editor = inject<Ref<Editor>>("editor");
const editorProps = inject<Ref<EditorProps>>("editorProps");

// 对话框状态
const showDialog = ref(false);
const activeTab = ref<"url" | "upload">("url");
const imageUrl = ref("");
const loading = ref(false);
const uploadRef = ref();
const previewImage = ref<string>("");
const selectedFile = ref<File | null>(null);

// 验证 URL 是否有效
const isValidUrl = computed(() => {
  if (!imageUrl.value.trim()) return false;
  try {
    const url = new URL(imageUrl.value.trim());
    return url.protocol === "http:" || url.protocol === "https:";
  } catch {
    return false;
  }
});

// 处理点击按钮
const handleClick = () => {
  showDialog.value = true;
  activeTab.value = "url";
  imageUrl.value = "";
  previewImage.value = "";
  selectedFile.value = null;
};

// 检查编辑器是否已就绪
const isEditorReady = (): boolean => {
  return !!(
    editor?.value &&
    editor.value.view &&
    editor.value.view.state
  );
};

// 处理从 URL 插入图片
const handleInsertFromUrl = async () => {
  if (!isValidUrl.value || !editor?.value || loading.value) return;

  loading.value = true;
  try {
    const url = imageUrl.value.trim();
    let finalSrc = url;

    // 如果不是 base64，转换为 base64
    if (!isBase64Image(url)) {
      finalSrc = await imageUrlToBase64(url);
    }

    // 等待编辑器就绪
    await nextTick();
    if (!isEditorReady()) {
      throw new Error("编辑器尚未就绪，请稍后再试");
    }

    // 插入图片
    editor.value
      .chain()
      .focus()
      .setImage({ src: finalSrc })
      .run();

    // 关闭对话框
    showDialog.value = false;
    imageUrl.value = "";
  } catch (error) {
    console.error("Failed to insert image from URL:", error);
    // 可以在这里显示错误提示
  } finally {
    loading.value = false;
  }
};

// 处理文件选择
const handleFileChange = (file: UploadFile) => {
  if (!file.raw) return;

  selectedFile.value = file.raw;

  // 预览图片
  const reader = new FileReader();
  reader.onload = (e) => {
    if (e.target?.result && typeof e.target.result === "string") {
      previewImage.value = e.target.result;
    }
  };
  reader.readAsDataURL(file.raw);
};

// 处理移除预览
const handleRemovePreview = () => {
  previewImage.value = "";
  selectedFile.value = null;
  uploadRef.value?.clearFiles();
};

// 处理从文件插入图片
const handleInsertFromFile = async () => {
  if (!selectedFile.value || !editor?.value || loading.value) return;

  loading.value = true;
  try {
    // 等待编辑器就绪
    await nextTick();
    if (!isEditorReady()) {
      throw new Error("编辑器尚未就绪，请稍后再试");
    }

    // 如果有 onFileUpload 回调，先尝试上传
    if (editorProps?.value?.onFileUpload) {
      try {
        const result = await editorProps.value.onFileUpload(selectedFile.value);
        // 如果上传成功，使用返回的 URL
        editor.value
          .chain()
          .focus()
          .setImage({ src: result.url })
          .run();
      } catch (error) {
        // 上传失败，使用 base64
        const base64 = await fileToBase64(selectedFile.value);
        editor.value
          .chain()
          .focus()
          .setImage({ src: base64 })
          .run();
      }
    } else {
      // 直接转换为 base64
      const base64 = await fileToBase64(selectedFile.value);
      editor.value
        .chain()
        .focus()
        .setImage({ src: base64 })
        .run();
    }

    // 关闭对话框
    showDialog.value = false;
    previewImage.value = "";
    selectedFile.value = null;
    uploadRef.value?.clearFiles();
  } catch (error) {
    console.error("Failed to insert image from file:", error);
    // 可以在这里显示错误提示
  } finally {
    loading.value = false;
  }
};

// 处理取消
const handleCancel = () => {
  showDialog.value = false;
  imageUrl.value = "";
  previewImage.value = "";
  selectedFile.value = null;
  uploadRef.value?.clearFiles();
};
</script>

<style scoped lang="scss">
.image-insert-tabs {
  :deep(.el-tabs__content) {
    padding: 16px 0;
  }
}

.image-upload-area {
  width: 100%;
}

.upload-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  text-align: center;
}

.upload-icon {
  font-size: 48px;
  color: var(--editor-text-color-secondary, #999);
  margin-bottom: 16px;
}

.upload-text {
  font-size: var(--editor-font-size-medium, 14px);
  color: var(--editor-text-color);
  margin-bottom: 8px;
}

.upload-hint {
  font-size: var(--editor-font-size-small, 12px);
  color: var(--editor-text-color-secondary, #999);
}

.image-preview {
  margin-top: 16px;
  padding: 16px;
  border: 1px solid var(--editor-border-color-light, #e0e0e0);
  border-radius: var(--editor-radius-medium, 4px);
  text-align: center;
}

.image-preview-container {
  width: 100%;
  max-width: 100%;
  max-height: 400px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
  background-color: var(--editor-container-background, #f4f5f7);
  border-radius: var(--editor-radius-small, 2px);
  padding: 8px;

  img {
    max-width: 100%;
    max-height: 400px;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--editor-radius-small, 2px);
    display: block;
  }
}

.image-preview-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
}
</style>

